package com.yjq.test;

import jdk.internal.util.xml.impl.Input;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.io.*;
import java.util.List;
import java.util.zip.ZipInputStream;

public class InitDB {
    /**
     * 生成 activiti的数据库表
     */
    @Test
    public void testCreateDbTable() {
        //使用classpath下的activiti.cfg.xml中的配置创建processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(processEngine);
    }


    /**
     * 部署流程定义，文件上传方式
     */
    @Test
    public void testDeployment(){
        //1、创建ProcessEngine
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //2、得到repositoryService实例
        RepositoryService repositoryService=processEngine.getRepositoryService();
        //3、使用RepositoryService进行部署
        Deployment deployment=repositoryService.createDeployment()
                .addClasspathResource("bpmn/level.bpmn")
                //png资源命名是又规则的
                .addClasspathResource("bpmn/level.png")
                .name("请假审批流程")
                .deploy();
        //4、输出部署信息
        System.out.println("流程部署id："+deployment.getId());
        System.out.println("流程部署名称："+deployment.getName());
    }


    /**
     * 以zip的形式实现文件上传到数据库
     */
    public void deployProcessByZip(){
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //定义zip输入流
        InputStream inputStream=this
                .getClass()
                .getClassLoader()
                .getResourceAsStream("bpmn/level.zip");
        ZipInputStream zipInputStream=new ZipInputStream(inputStream);
        //获取repositoryService
        RepositoryService repositoryService=processEngine.getRepositoryService();
        //流程部署
        Deployment deployment=repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();
        System.out.println("流程部署id："+deployment.getId());
        System.out.println("流程部署名称："+deployment.getName());

    }


    /**
     * 启动流程实例
     */
    @Test
    public void testStartProcess(){
        //1、得到流程引擎
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //2、获取RuntimeService
        RuntimeService runtimeService=processEngine.getRuntimeService();
        //3、根据流程定义id启动流程
        ProcessInstance processInstance=runtimeService.startProcessInstanceByKey("myLeave");
        // 输出内容
        System.out.println("流程定义id："+processInstance.getProcessDefinitionId());
        System.out.println("流程实例id:"+processInstance.getId());
        System.out.println("当前活动id："+processInstance.getActivityId());
    }


    /**
     * 查看当前个人的待执行任务
     */
    @Test
    public void testFindPersonalTaskList(){
        //任务负责人
        String assignee = "张三";
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //创建TaskService
        TaskService taskService=processEngine.getTaskService();
        //根据流程的key,任务责任人 查询任务
        List<org.activiti.engine.task.Task> list=taskService.createTaskQuery()
                .processDefinitionKey("evection")
                .taskAssignee(assignee)
                .list();

        for (Task task:list){
            System.out.println("流程实例id："+task.getProcessInstanceId());
            System.out.println("任务id:"+task.getId());
            System.out.println("任务负责人："+task.getAssignee());
            System.out.println("任务名称："+task.getName());
        }
    }

    /**
     *
     * 完成任务
     */
    @Test
    public void finishTask(){
        // 获取引擎
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        // 获取taskService
        TaskService taskService=processEngine.getTaskService();

        //根据流程key，任务的负责人 查询任务
        // 返回一个任务对象
        Task task=taskService.createTaskQuery()
                .processDefinitionKey("myLeave")//流程key
                .taskAssignee("worker")//要查询的负责人
                .singleResult();
        // =====在这个过程中完成相应的逻辑业务处理======

        // 完成任务，参数，任务id
        taskService.complete(task.getId());
    }


    /**
     * 查询流程定义
     */
    @Test
    public void queryProcessDefinition(){
        // 获取引擎
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        // repositoryService
        RepositoryService repositoryService=processEngine.getRepositoryService();
        // 得到ProcessDefinitionQuery 对象
        ProcessDefinitionQuery definitionQuery=repositoryService.createProcessDefinitionQuery();
        // 查询出当前所有的流程定义
        // 条件：processDefinitionKey = evection
        // orderByProcessDefinitionVersion 按照版本排序
        // desc倒叙
        // list返回集合
        List<ProcessDefinition> definitionList=definitionQuery.processDefinitionKey("myLeave")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        // 输出流程定义信息
        for (ProcessDefinition processDefinition:definitionList){
            System.out.println("流程定义：id="+processDefinition.getId());
            System.out.println("流程定义：name="+processDefinition.getName());
            System.out.println("任务关键字：key="+processDefinition.getKey());
            System.out.println("流程定义：version="+processDefinition.getVersion());
            System.out.println("流程部署Id:"+processDefinition.getDeploymentId());
        }
    }


    /**
     *查询流程实例
     */
    @Test
    public void queryProcessInstance(){
        // 流程定义key
        String processDefinitionKey="evection";
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //获取RuntimeService
        RuntimeService runtimeService=processEngine.getRuntimeService();
        List<ProcessInstance> list=runtimeService
                .createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)
                .list();
        //输出流程实例信息
        for (ProcessInstance processInstance:list){
            System.out.println("=======================");
            System.out.println("流程实例id:"+processInstance.getId());
            System.out.println("所属流程定义id:"+processInstance.getProcessDefinitionId());
            System.out.println("是否执行完成："+processInstance.isEnded());
            System.out.println("是否暂停："+processInstance.isSuspended());
            System.out.println("当前活动标识："+processInstance.getActivityId());
            System.out.println("业务关键字："+processInstance.getBusinessKey());
        }
    }

    /**
     * 删除部署流程
     */
    @Test
    public void deleteDeployment(){
        // 流程部署id
        String deploymentId="115001";
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService=processEngine.getRepositoryService();
        //如果你删除的是还在进行中的流程实例，那么会出现报错
//        repositoryService.deleteDeployment(deploymentId);
        //但是如果你在方法后追加true，那么表示可以强=强制删除该实例
        repositoryService.deleteDeployment(deploymentId,true);
    }


    /**
     * 将流程的bpmn文件和图片下载下来
     */
    @Test
    public void testDownloadFile() throws IOException {
        //首先获取当前的流程部署信息
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //获取流程仓库服务
        RepositoryService repositoryService=processEngine.getRepositoryService();
        //根据他的名称查询流程的定义
        ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myLeave")
                .singleResult();

        //得到部署的id
        String deploymentId=processDefinition.getDeploymentId();
        //获取图片和bpmn文件的存放位置
        //图片输入流
        InputStream inputStream=repositoryService.getResourceAsStream(deploymentId,processDefinition.getDiagramResourceName());
        //bpmn文件输入流
        InputStream inputStream1=repositoryService.getResourceAsStream(deploymentId,processDefinition.getResourceName());
        //字节输出流的创建
        FileOutputStream bpmnOut=new FileOutputStream("d://leave.bpmn");
        FileOutputStream pngOut=new FileOutputStream("d://leave.png");
        //将读取到的数据转换到指定位置
        byte[] bytes=new byte[1024*1024];
        int len=0;
        while((len=inputStream1.read(bytes))>0){
            bpmnOut.write(bytes,0,len);
        }
        bytes=new byte[8192];
        while((len=inputStream.read(bytes))>0){
            pngOut.write(bytes,0,len);
        }
        //关闭流
        pngOut.close();
        bpmnOut.close();
        inputStream1.close();
        inputStream.close();
    }


    /**
     * 查询流程实例的历史记录
     */
    @Test
    public void queryProcessInstanceHistory(){
        ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
        //获取历史服务
        HistoryService historyService=processEngine.getHistoryService();
        //获取actions表的查询对象
        HistoricActivityInstanceQuery instanceQuery=historyService.createHistoricActivityInstanceQuery()
                .processInstanceId("60001");
        //查询 actions表，条件，根据DefinitionId查询，查询一个流程的所有历史信息
//        instanceQuery.processInstanceId("32504");
        //添加排序操作
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        // 查询所有内容
        List<HistoricActivityInstance> activityInstances=instanceQuery.list();
        //输出
        for (HistoricActivityInstance hi:activityInstances){
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("==========================================");
        }
    }
}
